package com.seckill.authsdk.gateway.util;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import com.seckill.common.domain.R;
import com.seckill.common.domain.dto.LoginUserDTO;
import com.seckill.common.exceptions.ForbiddenException;
import com.seckill.common.exceptions.UnauthorizedException;
import com.seckill.common.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.AntPathMatcher;

import java.util.*;
import java.util.stream.Collectors;

import static com.seckill.auth.common.constants.AuthErrorInfo.ADMIN_ROLE_ID;
import static com.seckill.auth.common.constants.AuthErrorInfo.Code.EXPIRED_TOKEN_CODE;
import static com.seckill.auth.common.constants.AuthErrorInfo.Code.INVALID_TOKEN_CODE;
import static com.seckill.auth.common.constants.AuthErrorInfo.Msg.*;
import static com.seckill.auth.common.constants.JwtConstants.*;

@Slf4j
public class AuthUtil {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    private final JwtSignerHolder jwtSignerHolder;
    private final StringRedisTemplate stringRedisTemplate;

    public AuthUtil(JwtSignerHolder jwtSignerHolder, StringRedisTemplate stringRedisTemplate) {
        this.jwtSignerHolder = jwtSignerHolder;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    public R<LoginUserDTO> parseToken(String token) {
        // 1.校验token是否为空
        if(StringUtils.isBlank(token)){
            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
        }
        JWT jwt = null;
        try {
            jwt = JWT.of(token).setSigner(jwtSignerHolder.getJwtSigner());
        } catch (Exception e) {
            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
        }
        // 2.校验jwt是否有效
        if (!jwt.verify()) {
            // 验证失败，返回空
            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN);
        }
        // 3.校验是否过期
        try {
            JWTValidator.of(jwt).validateDate();
        } catch (ValidateException e) {
            return R.error(EXPIRED_TOKEN_CODE, EXPIRED_TOKEN);
        }
        // 4.数据格式校验
        Object userPayload = jwt.getPayload(PAYLOAD_USER_KEY);
        if (userPayload == null) {
            // 数据为空
            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN_PAYLOAD);
        }

        // 5.数据解析
        LoginUserDTO userDTO;
        try {
            userDTO = ((JSONObject)userPayload).toBean(LoginUserDTO.class);
        } catch (RuntimeException e) {
            // token格式有误
            return R.error(INVALID_TOKEN_CODE, INVALID_TOKEN_PAYLOAD);
        }

        // 6.返回
        return R.ok(userDTO);
    }

    public void checkAuth(String antPath, R<LoginUserDTO> r){
        // antPath 以admin  开头的，是管理端权限
        if(antPath.startsWith("admin")){
            if(!r.success()){
                // 未登录，直接报错
                throw new UnauthorizedException(r.getCode(), r.getMsg());
            }else{
                if(!r.getData().getRoleId().equals(ADMIN_ROLE_ID)){
                    throw new ForbiddenException(FORBIDDEN);
                }
            }
        }
    }
}
